/**
 * Copyright (c) 2018 人人开源 All rights reserved.
 *
 * https://www.renren.io
 *
 * 版权所有，侵权必究！
 */

package io.renren.modules.security.oauth2;

import com.google.gson.Gson;
import io.renren.common.constant.Constant;
import io.renren.common.exception.ErrorCode;
import io.renren.common.utils.HttpContextUtils;
import io.renren.common.utils.Result;
import java.util.Arrays;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * oauth2过滤器
 *
 * @author Mark sunlightcs@gmail.com
 */
public class Oauth2Filter extends AuthenticatingFilter {

  @Override
  protected AuthenticationToken createToken(ServletRequest request, ServletResponse response)
      throws Exception {
    //获取请求token
    String token = getRequestToken((HttpServletRequest) request);

    if (StringUtils.isBlank(token)) {
      return null;
    }

    return new Oauth2Token(token);
  }

  @Override
  protected boolean isAccessAllowed(ServletRequest request, ServletResponse response,
      Object mappedValue) {
    if (((HttpServletRequest) request).getMethod().equals(RequestMethod.OPTIONS.name())) {
      return true;
    }

    return false;
  }

  @Override
  protected boolean onAccessDenied(ServletRequest request, ServletResponse response)
      throws Exception {
    //获取请求token，如果token不存在，直接返回401
    String token = getRequestToken((HttpServletRequest) request);
    String requestURI = ((HttpServletRequest) request).getRequestURI();
    // 忽略拦截的地址
    String[] igroneUrlArray = {"/sys/oss/download"};
    String contextPath = ((HttpServletRequest) request).getContextPath();
    boolean ignore = Arrays.stream(igroneUrlArray)
        .anyMatch(igroneUrl -> requestURI.equals(contextPath + igroneUrl));
    if (ignore) {
      return true;
    }
    if (StringUtils.isBlank(token)) {
      HttpServletResponse httpResponse = (HttpServletResponse) response;
      httpResponse.setContentType("application/json;charset=utf-8");
      httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
      httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtils.getOrigin());

      String json = new Gson().toJson(new Result().error(ErrorCode.UNAUTHORIZED));

      httpResponse.getWriter().print(json);

      return false;
    }

    return executeLogin(request, response);
  }

  @Override
  protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e,
      ServletRequest request, ServletResponse response) {
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    httpResponse.setContentType("application/json;charset=utf-8");
    httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
    httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtils.getOrigin());
    try {
      //处理登录失败的异常
      Throwable throwable = e.getCause() == null ? e : e.getCause();
      Result r = new Result().error(HttpStatus.SC_UNAUTHORIZED, throwable.getMessage());

      String json = new Gson().toJson(r);
      httpResponse.getWriter().print(json);
    } catch (IOException e1) {

    }

    return false;
  }

  /**
   * 获取请求的token
   */
  private String getRequestToken(HttpServletRequest httpRequest) {
    //从header中获取token
    String token = httpRequest.getHeader(Constant.TOKEN_HEADER);

    //如果header中不存在token，则从参数中获取token
    if (StringUtils.isBlank(token)) {
      token = httpRequest.getParameter(Constant.TOKEN_HEADER);
    }

    return token;
  }

}
